package com.qd.panda.service.card;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.exception.ApiException;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.card.*;
import com.qd.common.panda.domain.entity.card.redeemcode.CardRedeemCodeDTO;
import com.qd.common.panda.domain.entity.card.redeemcode.PlanRedeemCodeDTO;
import com.qd.common.panda.domain.entity.card.redeemcode.PlanRedeemCodeDetailDTO;
import com.qd.common.panda.domain.entity.card.third.sync.ThirdPartyListDTO;
import com.qd.panda.model.*;
import com.qd.panda.service.card.collect.CollectCardService;
import com.qd.panda.service.card.third.ThirdPartyService;
import com.qd.panda.service.card.third.sync.ThirdPartyListService;
import com.qd.panda.service.card.third.sync.ThirdPartySyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * 优惠卷
 *
 * @author sjk
 * @create 2023-04-21 13:42
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CardPlanHolderService {
    private final CardPlanService cardPlanService;
    private final CardPlanRedeemCodeService cardPlanRedeemCodeService;
    private final CardInfoService cardInfoService;
    private final CardInfoDetailService cardInfoDetailService;
    private final UserCardService userCardService;
    private final CollectCardService collectCardService;
    private final ThirdPartyService thirdPartyService;
    private final ThirdPartyListService thirdPartyListService;
    private final ThirdPartySyncService thirdPartySyncService;

    @Transactional(rollbackFor = Exception.class)
    public void redeemVoucher(String userId, String mobile, String redeemCode) {
        CardPlanRedeemCodeDTO cardPlanRedeemCodeDTO = Optional.ofNullable(cardPlanRedeemCodeService.getByIdDto(redeemCode)).orElseThrow(() -> new ApiException("请输入正确的兑换码"));
        if (StringUtils.hasLength(cardPlanRedeemCodeDTO.getUserId())) {
            if (userId.equals(cardPlanRedeemCodeDTO.getUserId())) {
                throw new ApiException("已经兑换成功，请勿重复兑换");
            } else {
                throw new ApiException("当前码已经兑换给其他用户");
            }
        }
        if (collectCardService.existsByPlanId(cardPlanRedeemCodeDTO.getPlanId())) {
            throw new ApiException("已经配置了自动领卷，不支持兑换");
        }
        cardPlanRedeemCodeDTO.setUserId(userId);
        cardPlanRedeemCodeService.update(cardPlanRedeemCodeDTO);

        List<CardInfoDetail> cardInfoDetails = updateCardInfoDetail(userId, mobile, cardPlanRedeemCodeDTO.getPlanId(), redeemCode);
        saveUserCard(userId, cardInfoDetails);
        CardPlan cardPlan = cardPlanService.getById(cardPlanRedeemCodeDTO.getPlanId());
        if (StringUtils.hasLength(cardPlan.getThirdParty())) {
            //不为空说明用的是第三方券商生成的码，这里就需要更新状态
            couponUsed(cardInfoDetails);
        }
        cardInfoDetails.clear();
        cardPlanRedeemCodeDTO.freeData();
    }

    private void couponUsed(List<CardInfoDetail> cardInfoDetails) {
        LocalDateTime redemptionTime = Optional.ofNullable(cardInfoDetails.get(0).getRedemptionTime()).orElse(LocalDateTime.now());
        List<String> cardIds = cardInfoDetails.stream().map(CardInfoDetail::getCardId).collect(toList());
        List<ThirdPartyList> thirdPartyLists = thirdPartyListService.getListByCardIds(cardIds);
        if (!thirdPartyLists.isEmpty()) {
            for (ThirdPartyList thirdPartyList : thirdPartyLists) {
                thirdPartyList.setState(PandaConstant.USE_STATE_1);
                thirdPartyList.setRedemptionTime(redemptionTime);
            }
            thirdPartyListService.updateBatchIds(thirdPartyLists);
            thirdPartyLists.clear();
        }
        cardIds.clear();
    }

    private void saveUserCard(String userId, List<CardInfoDetail> cardInfoDetails) {
        List<UserCard> list = new ArrayList<>(cardInfoDetails.size());
        for (CardInfoDetail cardInfoDetail : cardInfoDetails) {
            UserCard userCard = new UserCard();
            userCard.setValidityEndTime(cardInfoDetail.getValidityEndTime());
            userCard.setState(PandaConstant.USE_STATE_1);
            userCard.setUserId(userId);
            userCard.setCardMsgId(cardInfoDetail.getCardMsgId());
            userCard.setCardId(cardInfoDetail.getCardId());
            userCard.setRedemptionTime(cardInfoDetail.getRedemptionTime());
            list.add(userCard);
        }
        userCardService.saveBatch(list);
        list.clear();
    }


    private List<CardInfoDetail> updateCardInfoDetail(String userId, String mobile, String planId, String redeemCode) {
        LocalDateTime now = LocalDateTime.now();
        LocalDate currentDate = LocalDate.now();
        List<CardInfoDetail> cardInfoDetailList = cardInfoDetailService.getListByPlanIdAndRedeemCode(planId, redeemCode);
        if (null == cardInfoDetailList || cardInfoDetailList.isEmpty()) {
            throw new ApiException("不存在需要兑换的信息");
        }
        Set<String> cardMsgIdList = cardInfoDetailList.stream().map(CardInfoDetail::getCardMsgId).collect(Collectors.toSet());
        List<CardInfo> cardInfoList = cardInfoService.checkIds(cardMsgIdList);
        Map<String, Integer> volumeValidityMap = new HashMap<>(cardInfoList.size());
        for (CardInfo cardInfo : cardInfoList) {
            if (currentDate.isBefore(cardInfo.getUseStartTime())) {
                throw new ApiException("请在[" + cardInfo.getUseStartTime().toString() + "]开始兑换");
            }
            if (currentDate.isAfter(cardInfo.getUseEndTime())) {
                throw new ApiException("超过规定兑换时间，不能兑换");
            }
            volumeValidityMap.put(cardInfo.getCardMsgId(), cardInfo.getVolumeValidity());
        }
        cardInfoDetailList.forEach(cardInfoDetail -> {
            cardInfoDetail.setValidityEndTime(currentDate.plusDays(volumeValidityMap.get(cardInfoDetail.getCardMsgId())));
            cardInfoDetail.setMobile(mobile);
            cardInfoDetail.setUserId(userId);
            cardInfoDetail.setRedemptionTime(now);
            cardInfoDetail.setUseState(PandaConstant.USE_STATE_1);
        });
        cardInfoDetailService.updateBatchIds(cardInfoDetailList);
        return cardInfoDetailList;
    }

    @Transactional(rollbackFor = Exception.class)
    public CardPlanDTO save(CardPlanDTO dto) {
        dto.setPlanId(IdWorker.getIdStr());
        addCardInfo(dto);
        if (dto.getInfiniteQuantity().equals(ConstantDto.SF0)) {
            //只有不是无限数量的才需要生成兑换码
            buildRedeemCodeList(dto);
        }
        cardPlanService.save(dto);
        return dto;
    }

    @Transactional(rollbackFor = Exception.class)
    public CardPlanDTO update(CardPlanDTO dto) {
        CardPlan cardPlan = Optional.ofNullable(cardPlanService.getById(dto.getPlanId())).orElseThrow(() -> new ApiException("计划ID值错误"));
        if (null != dto.getAllocatedQuantity() && dto.getAllocatedQuantity() > 0) {
            if (!cardPlan.getAllocatedQuantity().equals(dto.getAllocatedQuantity())) {
                throw new ApiException("不能修改码数量");
            }
        }
        updateCardInfo(dto);
        cardPlanService.update(dto);
        return dto;
    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(String planId) {
        cardPlanService.removeById(planId);
        cardInfoService.removeByPlanId(planId);
        cardPlanRedeemCodeService.removeByPlanId(planId);
        cardInfoDetailService.removeByPlanId(planId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteIds(List<String> ids) {
        for (String id : ids) {
            delete(id);
        }
    }

    private void buildRedeemCodeList(CardPlanDTO dto) {
        if (StringUtils.hasLength(dto.getThirdParty())) {
            if (Boolean.FALSE.equals(thirdPartyService.isExistsById(dto.getThirdParty()))) {
                throw new ApiException("第三方券商值错误");
            }
        }
        Integer allocatedQuantity = dto.getAllocatedQuantity();
        List<CardInfoDTO> cardInfoList = dto.getCardInfoList();
        //总的发卷数量
        Integer all = 0;
        Map<BigDecimal, LinkedList<String>> map = new HashMap<>(8);
        Map<String, Long> eventMap = new HashMap<>(8);
        for (CardInfoDTO cardInfoDTO : cardInfoList) {
            all += cardInfoDTO.getCardQuantity();
            setThird(dto, cardInfoDTO, map, eventMap);
        }
        all = allocatedQuantity * all;
        log.info("总的发卷数量: {}", all);
        List<CardPlanRedeemCode> list = new ArrayList<>(allocatedQuantity);
        List<CardInfoDetail> detailList = new ArrayList<>(all);
        List<ThirdPartyList> thirdPartyLists = new ArrayList<>(all);
        for (int i = 0; i < allocatedQuantity; i++) {
            String redeemCode = RandomUtil.randomString(16);
            CardPlanRedeemCode cardPlanRedeemCode = new CardPlanRedeemCode();
            cardPlanRedeemCode.setPlanId(dto.getPlanId());
            cardPlanRedeemCode.setRedeemCode(redeemCode);
            list.add(cardPlanRedeemCode);
            for (CardInfoDTO cardInfoDTO : cardInfoList) {
                LinkedList<String> codeList = map.get(cardInfoDTO.getDiscountAmount());
                for (int j = 0; j < cardInfoDTO.getCardQuantity(); j++) {
                    CardInfoDetail cardInfoDetail = createCardIfoDetail(dto, cardInfoDTO, redeemCode);
                    detailList.add(cardInfoDetail);
                    if (StringUtils.hasLength(dto.getThirdParty())) {
                        ThirdPartyList thirdPartyList = createThirdPartyList(codeList, cardInfoDetail);
                        thirdPartyLists.add(thirdPartyList);
                    }
                }
            }
        }
        if (!list.isEmpty()) {
            cardPlanRedeemCodeService.saveBatch(list);
            list.clear();
        }
        if (!detailList.isEmpty()) {
            cardInfoDetailService.saveBatch(detailList);
            detailList.clear();
        }
        if (!thirdPartyLists.isEmpty()) {
            thirdPartyListService.updateBatchIds(thirdPartyLists);
            thirdPartyLists.clear();
        }
        if (!eventMap.isEmpty()) {
            List<ThirdPartySync> thirdPartySyncs = new ArrayList<>(eventMap.size());
            for (String event : eventMap.keySet()) {
                ThirdPartySync thirdPartySync = thirdPartySyncService.getById(event);
                if (null != thirdPartySync) {
                    thirdPartySync.setUseQuantity(Optional.ofNullable(thirdPartySync.getUseQuantity()).orElse(0L) + eventMap.get(event));
                    thirdPartySyncs.add(thirdPartySync);
                }
            }
            if (!thirdPartySyncs.isEmpty()) {
                thirdPartySyncService.updateBatchIds(thirdPartySyncs);
                thirdPartySyncs.clear();
            }
            eventMap.clear();
        }
        if (!map.isEmpty()) {
            map.clear();
        }
    }

    private CardInfoDetail createCardIfoDetail(CardPlanDTO dto, CardInfoDTO cardInfoDTO, String redeemCode) {
        CardInfoDetail cardInfoDetail = new CardInfoDetail();
        cardInfoDetail.setCardId(IdWorker.getIdStr());
        cardInfoDetail.setRedeemCode(redeemCode);
        cardInfoDetail.setCardMsgId(cardInfoDTO.getCardMsgId());
        cardInfoDetail.setPlanId(dto.getPlanId());
        cardInfoDetail.setUseState(PandaConstant.USE_STATE_0);
        return cardInfoDetail;
    }

    private ThirdPartyList createThirdPartyList(LinkedList<String> codeList, CardInfoDetail cardInfoDetail) {
        String thirdCouponCode = codeList.pop();
        ThirdPartyList thirdPartyList = new ThirdPartyList();
        thirdPartyList.setThirdCouponCode(thirdCouponCode);
        thirdPartyList.setCardId(cardInfoDetail.getCardId());
        thirdPartyList.setState(PandaConstant.USE_STATE_0);
        return thirdPartyList;
    }

    private void setThird(CardPlanDTO dto, CardInfoDTO cardInfoDTO, Map<BigDecimal, LinkedList<String>> map, Map<String, Long> eventMap) {
        if (StringUtils.hasLength(dto.getThirdParty())) {
            if (!cardInfoDTO.getDiscountMethod().equals(PandaConstant.DISCOUNT_METHOD_3)) {
                throw new ApiException("设置了第三方券商以后只能添加现金券");
            }
            LinkedList<String> list = map.get(cardInfoDTO.getDiscountAmount());
            if (null == list || list.isEmpty()) {
                int quantity = cardInfoDTO.getCardQuantity() * dto.getAllocatedQuantity();
                List<ThirdPartyListDTO> thirdCouponCodeList = thirdPartyListService.getBaseMapper().getThirdCouponCodeList(dto.getThirdParty(), cardInfoDTO.getDiscountAmount(), quantity);
                if (thirdCouponCodeList.size() < quantity) {
                    log.info("优惠券数量不够,需要的数量: {},实际数量: {}", quantity, thirdCouponCodeList.size());
                    throw new ApiException("优惠券数量不够");
                }
                list = thirdCouponCodeList.stream().map(ThirdPartyListDTO::getThirdCouponCode).collect(Collectors.toCollection(LinkedList::new));
                map.put(cardInfoDTO.getDiscountAmount(), list);
                Map<String, Long> sumAll = thirdCouponCodeList.stream().collect(Collectors.groupingBy(ThirdPartyListDTO::getEvent, Collectors.counting()));
                eventMap.putAll(sumAll);
            } else {
                throw new ApiException("不支持设置相同金额的现金券多次");
            }
        }
    }

    private void addCardInfo(CardPlanDTO dto) {
        List<CardInfoDTO> cardInfoList = dto.getCardInfoList();
        if (null == cardInfoList || cardInfoList.isEmpty()) {
            return;
        }
        String infiniteQuantity = dto.getInfiniteQuantity();
        if (StringUtils.hasLength(infiniteQuantity)) {
            if (infiniteQuantity.equals(ConstantDto.SF1)) {
                if (cardInfoList.size() != 1) {
                    throw new ApiException("设置无限数量以后,只能添加一种类型的券");
                }
                if (dto.getAllocatedQuantity() != -1) {
                    throw new ApiException("设置无限数量以后,码的数量只能为-1");
                }
            } else {
                if (dto.getAllocatedQuantity() < 1) {
                    throw new ApiException("码数量只能为必须大于0");
                }
            }
        }
        for (CardInfoDTO cardInfoDTO : cardInfoList) {
            if (StringUtils.hasLength(infiniteQuantity)) {
//                if (infiniteQuantity.equals(ConstantDto.SF1)) {
//                    if (cardInfoDTO.getCardQuantity() != -1) {
//                        throw new ApiException("设置无限数量以后,券的数量只能为-1");
//                    }
//                } else {
                if (cardInfoDTO.getCardQuantity() < 1) {
                    throw new ApiException("券的数量必须大于0");
                }
//                }
            }
            if (!StringUtils.hasLength(cardInfoDTO.getPlanId())) {
                cardInfoDTO.setPlanId(dto.getPlanId());
            }
            if (!StringUtils.hasLength(cardInfoDTO.getCardMsgId())) {
                cardInfoDTO.setCardMsgId(IdWorker.getIdStr());
            }
            cardInfoDTO.setOperator(dto.getOperator());
            cardInfoDTO.setOrgId(dto.getOrgId());
            if (null == cardInfoDTO.getAddTime()) {
                cardInfoDTO.setAddTime(dto.getAddTime());
            }
            if (null == cardInfoDTO.getUpdateTime()) {
                cardInfoDTO.setUpdateTime(dto.getUpdateTime());
            }
            if (!StringUtils.hasLength(cardInfoDTO.getUseStartTime())) {
                if (StringUtils.hasLength(dto.getUseStartTime())) {
                    cardInfoDTO.setUseStartTime(dto.getUseStartTime());
                }
            }
            if (!StringUtils.hasLength(cardInfoDTO.getUseEndTime())) {
                if (StringUtils.hasLength(dto.getUseEndTime())) {
                    cardInfoDTO.setUseEndTime(dto.getUseEndTime());
                }
            }
            if (cardInfoDTO.getDiscountMethod().equals(PandaConstant.DISCOUNT_METHOD_1)) {
                if (null == cardInfoDTO.getDiscount()) {
                    throw new ApiException("折扣不能为空");
                }
                if (cardInfoDTO.getDiscount() < 1) {
                    throw new ApiException("折扣值不能小于1");
                }
            }
            if (null == cardInfoDTO.getVolumeValidity() || cardInfoDTO.getVolumeValidity() < 1) {
                if (null != dto.getVolumeValidity() && dto.getVolumeValidity() > 0) {
                    cardInfoDTO.setVolumeValidity(dto.getVolumeValidity());
                }
            }
            cardInfoService.validator(cardInfoDTO);
        }
        List<CardInfo> cardInfo = cardInfoService.dtoToModelList(cardInfoList);
        cardInfoService.saveBatch(cardInfo);
    }


    private void updateCardInfo(CardPlanDTO dto) {
        List<CardInfoDTO> cardInfoList = dto.getCardInfoList();
        if (null == cardInfoList || cardInfoList.isEmpty()) {
            return;
        }
        for (CardInfoDTO cardInfoDTO : cardInfoList) {
            if (!StringUtils.hasLength(dto.getPlanId())) {
                cardInfoDTO.setPlanId(dto.getPlanId());
            }
            if (!StringUtils.hasLength(cardInfoDTO.getCardMsgId())) {
                cardInfoDTO.setCardMsgId(IdWorker.getIdStr());
            }
            cardInfoDTO.setOperator(dto.getOperator());
            cardInfoDTO.setOrgId(dto.getOrgId());
            if (null == cardInfoDTO.getAddTime()) {
                cardInfoDTO.setAddTime(dto.getAddTime());
            }
            if (null == cardInfoDTO.getUpdateTime()) {
                cardInfoDTO.setUpdateTime(dto.getUpdateTime());
            }
            cardInfoService.validator(cardInfoDTO);
        }
        List<CardInfo> cardInfo = cardInfoService.dtoToModelList(cardInfoList);
        cardInfoService.updateBatchIds(cardInfo);
    }


    /**
     * 清理过期卷信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void cleanUpCard() {
        LocalDate localDate = LocalDate.now();
        List<CardInfoDetailDTO> cardInfoDetailDTOS = cardInfoDetailService.clearUpCard(localDate);
        if (!cardInfoDetailDTOS.isEmpty()) {
            List<String> cardIds = cardInfoDetailDTOS.stream().map(CardInfoDetailDTO::getCardId).collect(toList());
            thirdPartyListService.clearUp(cardIds);
            cardIds.clear();
            cardInfoDetailDTOS.clear();
        }
        userCardService.clearUpCard(localDate);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateUseCard(String cardId, String orderId, int state) {
        LocalDateTime now = LocalDateTime.now();
        CardInfoDetailDTO cardInfoDetail = cardInfoDetailService.getByIdDto(cardId);
        if (null != cardInfoDetail) {
            cardInfoDetail.setUseTime(now);
            cardInfoDetail.setUseState(state);
            cardInfoDetailService.update(cardInfoDetail);
            cardInfoDetail.freeData();
        }
        UserCardDTO cardDTO = userCardService.getByIdDto(cardId);
        if (null != cardDTO) {
            cardDTO.setUseTime(now);
            cardDTO.setOrderId(orderId);
            cardDTO.setState(state);
            userCardService.update(cardDTO);
            cardDTO.freeData();
        }
        //如果用了第三方的优惠券，也需要更新成未使用
        ThirdPartyListDTO thirdPartyListDTO = thirdPartyListService.getListByCardIdDto(cardId);
        if (null != thirdPartyListDTO) {
            thirdPartyListDTO.setUseTime(now);
            thirdPartyListDTO.setState(state);
            thirdPartyListService.update(thirdPartyListDTO);
            thirdPartyListDTO.freeData();
        }
    }

    @Transactional(readOnly = true)
    public PlanRedeemCodeDTO useRedeemCode(String planId) {
        CardPlanDTO cardPlanDTO = Optional.of(cardPlanService.getByIdDto(planId)).orElseThrow(() -> new ApiException("计划ID值错误"));
        cardPlanDTO.setCardInfoList(null);
        //卷总数量
        long totalCount = 0;
        //未兑换数量
        long redemptionNo = 0;
        //已兑换数量
        long redemptionYes = 0;
        //未使用数量
        long useNo = 0;
        //已使用数量
        long useYes = 0;
        PlanRedeemCodeDTO planRedeemCodeDTO = new PlanRedeemCodeDTO()
                .setCardPlanDTO(cardPlanDTO);
        List<CardRedeemCodeDTO> list = cardInfoDetailService.getBaseMapper().useRedeemCode(planId);
        if (!list.isEmpty()) {
            for (CardRedeemCodeDTO cardRedeemCodeDTO : list) {
                totalCount += cardRedeemCodeDTO.getTotalCount();
                redemptionNo += cardRedeemCodeDTO.getRedemptionNo();
                redemptionYes += cardRedeemCodeDTO.getRedemptionYes();
                useNo += cardRedeemCodeDTO.getUseNo();
                useYes += cardRedeemCodeDTO.getUseYes();
            }
            planRedeemCodeDTO.setCardRedeemCodeList(list);
        }
        planRedeemCodeDTO.setTotalCount(totalCount)
                .setRedemptionNo(redemptionNo)
                .setRedemptionYes(redemptionYes)
                .setUseNo(useNo)
                .setUseYes(useYes);
        return planRedeemCodeDTO;
    }

    @Transactional(readOnly = true)
    public IPage<PlanRedeemCodeDetailDTO> useRedeemCodeDetailPage(Page<PlanRedeemCodeDetailDTO> page, String planId, String cardMsgId, Integer type) {
//        QueryWrapper<CardInfoDetail> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("t1.plan_id", planId);
//        if (StringUtils.hasLength(cardMsgId)) {
//            queryWrapper.eq("t1.card_msg_id", cardMsgId);
//        }
//        if (type == 1) {
////            queryWrapper.orderByAsc("t2.redemption_time");
//            queryWrapper.isNotNull("t2.redemption_time");
//        } else if (type == 2) {
////            queryWrapper.orderByAsc("t2.use_time");
//            queryWrapper.isNotNull("t2.use_time");
//        } else {
//            throw new ApiException("类型值错误");
//        }
//        queryWrapper.groupBy("t2.mobile");
//        queryWrapper.orderByDesc("quantity");
//        IPage<PlanRedeemCodeDetailDTO> iPage = cardInfoDetailService.getBaseMapper().useRedeemCodeDetailPage(page, queryWrapper, type);
//        queryWrapper.clear();
        QueryWrapper<CardInfoDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t1.plan_id", planId);
        if (StringUtils.hasLength(cardMsgId)) {
            queryWrapper.eq("t1.card_msg_id", cardMsgId);
        }
        if (null == type) {
            throw new ApiException("type不能为空");
        }
        if (type == 1) {
            queryWrapper.isNotNull("t2.redemption_time");
        } else if (type == 2) {
            queryWrapper.eq("t2.state", type);
        } else {
            throw new ApiException("类型值错误");
        }
        IPage<PlanRedeemCodeDetailDTO> iPage;
        if (type == 1) {
            queryWrapper.groupBy("t2.mobile");
            queryWrapper.orderByDesc("quantity");
            iPage = cardInfoDetailService.getBaseMapper().exchangeRedeemCodeDetailPage(page, queryWrapper, type);
        } else {
            queryWrapper.groupBy("t3.mobile");
            queryWrapper.orderByDesc("quantity");
            iPage = cardInfoDetailService.getBaseMapper().useRedeemCodeDetailPage(page, queryWrapper, type);
        }
        queryWrapper.clear();
        return iPage;
    }

    @Transactional(rollbackFor = Exception.class)
    public void couponUsed(String thirdCouponCode, LocalDateTime now) {
        ThirdPartyListDTO thirdPartyListDTO = thirdPartyListService.getByIdDto(thirdCouponCode);
        log.info("第三方券码: {},thirdPartyListDTO: {}", thirdCouponCode, thirdPartyListDTO);
        if (null == thirdPartyListDTO) {
            return;
        }
        thirdPartyListDTO.setState(PandaConstant.USE_STATE_2);
        thirdPartyListDTO.setUseTime(now);
        thirdPartyListService.update(thirdPartyListDTO);


        if (StringUtils.hasLength(thirdPartyListDTO.getCardId())) {
            UserCardDTO userCardDTO = userCardService.getByIdDto(thirdPartyListDTO.getCardId());
            if (null != userCardDTO) {
                userCardDTO.setState(PandaConstant.USE_STATE_2);
                userCardDTO.setUseTime(now);
                userCardService.update(userCardDTO);
                userCardDTO.freeData();
            }

            CardInfoDetailDTO cardInfoDetailDTO = cardInfoDetailService.getByIdDto(thirdPartyListDTO.getCardId());
            if (null != cardInfoDetailDTO) {
                cardInfoDetailDTO.setUseState(PandaConstant.USE_STATE_2);
                cardInfoDetailDTO.setUseTime(now);
                cardInfoDetailService.update(cardInfoDetailDTO);
                cardInfoDetailDTO.freeData();
            }
        }

        thirdPartyListDTO.freeData();

    }

}